﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace DevelopAssistant.Format
{
    /// <summary>
    /// 功能描述：js 格式化 
    /// 版本号：v 1.0.0
    /// 创建作者：王晓东
    /// 更新时间：2016-02-17
    /// </summary>
    public class JavaScriptFormatHelper
    {
        public static string FormatToJavaScript(string strjs)
        {
            string result = string.Empty;

            try
            {
                if (string.IsNullOrEmpty(strjs))
                    return strjs;

                int temp_index = 0; //临时记数
                int space_index = 0; //空格计数  
                int break_index = 0; //换行计数

                strjs = strjs.Replace('\r', ' ');
                char[] chr_array = strjs.ToCharArray();
                List<char> chr_list = new List<char>();

                #region 处理换行，去除空格

                for (int i = 0, len = chr_array.Length; i < len; i++)
                {
                    char chr = chr_array[i];

                    if (chr == '\n')
                    {
                        break_index++;
                        if (break_index == 1)
                        {
                            chr_list.Add(chr);
                        }
                    }
                    if (chr != '\n')
                    {
                        break_index = 0;
                        if (chr == ' ')
                        {
                            space_index++;
                            if (space_index == 1)
                            {
                                chr_list.Add(chr);
                            }
                        }
                        if (chr != ' ')
                        {
                            space_index = 0;
                            if (chr == '{')
                            {
                                chr_list.Add(chr);
                                chr_list.Add('\n');
                            }
                            if (chr == '}')
                            {
                                int j = i;
                                char prechr = ' ';
                                while (j > 0)
                                {
                                    j = j - 1;
                                    char ch = chr_array[j];
                                    if (ch != ' ')
                                    {
                                        j = 0;
                                        prechr = ch;
                                        break;
                                    }
                                }
                                if (prechr != ';')
                                {
                                    chr_list.Add('\n');
                                }

                                chr_list.Add(chr);

                                if (i + 1 < len && chr_array[i + 1] != ';' && chr_array[i + 1] != ')'
                                    && chr_array[i + 1] != ',')
                                {
                                    chr_list.Add('\n');
                                }

                            }

                            if (chr == ',')
                            {
                                int j = i;
                                char prechr = ' ';
                                while (j > 0)
                                {
                                    j = j - 1;
                                    char ch = chr_array[j];
                                    if (ch != ' ')
                                    {
                                        j = 0;
                                        prechr = ch;
                                        break;
                                    }
                                }
                                chr_list.Add(chr);
                                if (prechr == '}')
                                {
                                    chr_list.Add('\n');
                                }                                
                            }

                            if (chr == ';')
                            {
                                chr_list.Add(chr);
                                chr_list.Add('\n');
                            }

                            if (chr == '*')
                            {
                                if (chr_array[i - 1] != '/')
                                {
                                    chr_list.Add('\n');
                                    chr_list.Add(chr);
                                }
                                else
                                {
                                    chr_list.Add(chr);
                                }
                            }

                            if (chr == '/')
                            {
                                if (i > 1 && chr_array[i - 1] == '*')
                                {
                                    chr_list.Add(chr);
                                    chr_list.Add('\n');
                                }
                                else
                                {
                                    chr_list.Add(chr);
                                }
                            }

                            if (chr != '{' && chr != '}' && chr != ';'
                                && chr != '*' && chr != '/' && chr != ',')
                            {
                                chr_list.Add(chr);
                            }
                        }
                    }

                }

                #endregion

                string temp_str = string.Concat(chr_list.ToArray());

                #region 处理缩进，格式化样式

                string tab = "   ";
                string[] lines_array = temp_str.Split('\n');
                List<string> result_list = new List<string>();
                foreach (string line in lines_array)
                {
                    if (!string.IsNullOrEmpty(line.Trim()))
                    {
                        string temp_line = line.ToString().Trim();

                        if (temp_line.TrimStart().StartsWith("})."))
                        {
                            temp_index = temp_index - 1;
                        }

                        if (temp_line == "{" || temp_line.EndsWith("{") )
                        {
                            if (temp_line.Contains("("))
                            {
                                temp_line = temp_line.Replace(") {", "){");
                            }
                            for (int i = 0; i < temp_index; i++)
                            {
                                temp_line = tab + temp_line;
                            }
                            temp_index = temp_index + 1;
                        }                       

                        if (!temp_line.Contains("{") && temp_line != "}" 
                            && !temp_line.EndsWith("});") 
                            && !temp_line.EndsWith("})(jQuery);")
                            && !temp_line.TrimStart().StartsWith("})."))
                        {

                            if (temp_line.EndsWith("};") || temp_line.EndsWith("},"))
                            {
                                temp_index = temp_index - 1;
                            }

                            if (temp_line.EndsWith("/*") && temp_line != "/*")
                            {
                                for (int i = 0; i < temp_index; i++)
                                {
                                    temp_line = tab + temp_line;
                                }
                                temp_line = temp_line.Replace("/*", "\r\n");
                                string temp_nline = string.Empty;
                                for (int i = 0; i < temp_index; i++)
                                {
                                    temp_nline = tab + temp_nline;
                                }
                                temp_line = temp_line + temp_nline + "/*";
                            }
                            else
                            {
                                for (int i = 0; i < temp_index; i++)
                                {
                                    temp_line = tab + temp_line;
                                }
                            }                            
                        }                       

                        if (temp_line == "}" || temp_line.EndsWith("});")
                            || temp_line.EndsWith("})(jQuery);"))
                        {                            
                            temp_index = temp_index - 1;
                            for (int i = 0; i < temp_index; i++)
                            {
                                temp_line = tab + temp_line;
                            }
                        }

                        result_list.Add(temp_line);
                        result = result + temp_line + "\r\n";

                    }

                }                 

                #endregion

                temp_str = null;
                chr_list.Clear();
                result_list.Clear();
                chr_list = null;
                result_list = null;

            }
            catch (Exception ex)
            {
                result = strjs;
            }
            return result;
        }

        public static string CompressToString(string strjs)
        {
            string result = string.Empty;

            Regex regex = new Regex(@"//.*\n");
            Match match = regex.Match(strjs);
            while (match.Success)
            {
                string matchstr = match.Groups[0].Value;
                strjs = strjs.Replace(matchstr, matchstr.Replace("//", "/*").Replace("\r\n", "*/\r\n"));
                match = match.NextMatch();
            }   
           
            strjs = strjs.Replace('\r', ' ');
            strjs = strjs.Replace('\n', ' ');

            strjs = Regex.Replace(strjs, " {1,}", "\n", RegexOptions.IgnoreCase)
                .Replace("('\n", "('").Replace("\n')", "')")
                .Replace("(\"\n", "(\"").Replace("\n\")", "\")")
                .Replace("\"\n", "\"").Replace("\n\"", "\"");

            strjs = strjs.Replace('\n', ' ');
            //string[] lines_array = strjs.Split('\n');                     

            return result;

        }
    }
}
